import axios from 'axios'
import store from '@/store'
import router from '@/router'
import { Message } from 'element-ui'
import qs from 'qs'

const request = axios.create()

function getBaseURL(url) {
  if (url.startsWith('/boss')) {
    return 'http://eduboss.lagou.com'
  } else {
    return 'http://edufront.lagou.com'
  }
}

request.interceptors.request.use(config => {
  // 根据请求的 URL 判断基地址，设置给config.baseURL
  config.baseURL = getBaseURL(config.url)

  // token 统一处理
  const { user } = store.state
  if (user && user.access_token) {
    config.headers.Authorization = user.access_token
  }

  return config
})

request.interceptors.response.use(response => {
  // 请求成功
  return response.data
}, async error => {
  // 请求失败
  if (error.response) {
    // 有返回响应
    return await processFailResponse(error)
  } else if (error.request) {
    // 请求发送成功，但没返回响应
    Message.error('请求超时，请重试')
    // 将失败往外抛出，交给外部继续处理
    return Promise.reject(error)
  } else {
    // 在设置请求时发⽣了⼀些失败，触发了错误（未知型错误）
    Message.error(`请求失败，${error.message}`)
    // 将失败往外抛出，交给外部继续处理
    return Promise.reject(error)
  }
})

let isRefreshingToken = false // 防止多个请求同时要刷新token
let requests = [] // 存储因为等待token刷新而被挂起的请求

export function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

async function processFailResponse(error) {
  const { response, config } = error
  const { status } = response
  let errorMessage = ''
  switch (status) {
    case 400:
      errorMessage = '请求参数错误'
      break
    case 401: {
      // token 失效，刷新token或跳回登录页
      if (isRefreshingToken) {
        return new Promise(resolve => {
          requests.push(() => {
            resolve(request(error.config)) // 请求真正被运行的时候，才返回结果，否则会被挂起
          })
        })
      }
      isRefreshingToken = true
      await sleep(1e3) // 这里是为了假设刷新缓存速度较慢，可能引发bug的条件
      const result = await refreshToken()
      isRefreshingToken = false
      console.log('refreshToken>>', result, config)
      // 重发之前的请求并返回
      if (result) {
        requests.forEach(fn => fn())
        requests = []
        return request(config)
      }
      requests = []
      break
    }
    case 403:
      errorMessage = '没有权限，请联系管理员'
      break
    case 404:
      errorMessage = '请求资源不存在'
      break
    default:
      errorMessage = '服务端错误，请联系管理员'
      break
  }
  return errorMessage && Message.error(errorMessage) && Promise.reject(error) // 将失败往外抛出，交给外部继续处理
}

/**
 * 成功返回true，失败返回false
 * @returns {boolean}
 */
function refreshToken() {
  // 如果store不存在user，跳登录页
  if (!store.state.user) {
    redirectLogin()
    // 阻止后续步骤，往外跑错误对象
    return false
  }

  return new Promise(resolve => {
    // 根据refresh_token 请求新的 access_token
    request({
      method: 'POST',
      url: '/front/user/refresh_token',
      data: qs.stringify({
        refreshtoken: store.state.user.refresh_token
      })
    }).then(data => {
      if (data.state !== 1) {
        // 获取token失败，重回登录页
        store.commit('setUser', null)
        redirectLogin()
        resolve(false)
      } else {
        // 获取token成功
        store.commit('setUser', data.content)
        console.log('获取token成功')
        resolve(true)
      }
    }).catch(() => {
      // 获取token时发生未知错误，重回登录页
      store.commit('setUser', null)
      redirectLogin()
      resolve(false)
    })
  })
}

function redirectLogin() {
  router.push({
    name: 'login',
    query: {
      redirect: router.currentRoute.fullPath
    }
  })
}

export default request
